<template>
  <canvas ref="canvas" class="fit overflow-hidden" @wheel="handleWheel" @click.stop="handleClick"></canvas>
  <q-resize-observer @resize="onResize"></q-resize-observer>
</template>

<script setup>
import { onMounted, ref } from 'vue'
import * as THREE from 'three'
import gsap from 'gsap'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

let scene = null, camera = null, renderer = null, controls = null
const raycaster = new THREE.Raycaster(), mouse = new THREE.Vector2()
const canvas = ref(null)
const screenSize = ref({ width: 0, height: 0 })
const initCanvas = () => {
  scene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(45, screenSize.value.width / screenSize.value.height, 0.1, 1000)
  camera.position.set(0, 0, 100)
  camera.lookAt(0, 0, 0)
  renderer = new THREE.WebGLRenderer({ canvas: canvas.value, antialias: true, alpha: true })
  renderer.setSize(screenSize.value.width, screenSize.value.height)
  // const cube = new THREE.Mesh(
  //   new THREE.BoxGeometry(5, 5, 5), new THREE.MeshBasicMaterial({ color: 0x00ff00 })
  // )
  // cube.position.set(1, 1, 1)
  const map = new THREE.TextureLoader().load(new URL('/src/assets/CONSOLE-BG.png', import.meta.url).href)
  const geometry = new THREE.BoxGeometry(2, 2, 2)
  const material = new THREE.MeshBasicMaterial(
    { map, vertexColors: false, transparent: true, opacity: 0.85, color: 0xffffff })
  const count = 500
  const instancedMesh = new THREE.InstancedMesh(geometry, material, count)
  const matrix = new THREE.Matrix4()
  // const color = new THREE.Color(0xffffff)
  for (let i = 0; i < count; i++) {
    matrix.setPosition(Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50)
    instancedMesh.setMatrixAt(i, matrix)
    // instancedMesh.setColorAt(i, color)
  }

  // instancedMesh.instanceColor.needsUpdate = true
  scene.add(instancedMesh)
  // scene.add(cube)

  const light = new THREE.DirectionalLight(0xff00000, 1)
  light.position.set(0, 0, 100)
  scene.add(light)

  controls = new OrbitControls(camera, renderer.domElement)
  controls.enableDamping = true
  // controls.dampingFactor = 0.1;
  controls.minDistance = 1
  controls.maxDistance = 500
  controls.maxPolarAngle = Math.PI * 200000
  // controls.addEventListener('change', () => {
  //   renderer.render(scene, camera)
  // })
  // controls.target.set(0, 0, 0)
  // controls.update()
  animate && animate()
  // renderer.render(scene, camera)
}
const animate = () => {
  requestAnimationFrame(animate)
  controls.update()
  renderer.render(scene, camera)
}
const onResize = (size) => {
  screenSize.value = size
  renderer && renderer.setSize(size.width, size.height)
}
const handleWheel = e => {
  e.preventDefault()
  // 将屏幕坐标转为 [-1, 1] 范围
  // const rect = renderer.domElement.getBoundingClientRect();
  // mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
  // mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;
  // 计算相机射线
  // raycaster.setFromCamera(mouse, camera);
  // // 和某个平面（或物体）相交，比如场景地面
  // const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0); // Y=0 平面
  // const point = new THREE.Vector3();
  // raycaster.ray.intersectPlane(plane, point);
  // // 设置 OrbitControls 的目标点为交点
  // controls.target.copy(point);
  // // 调整缩放
  // const delta = e.deltaY > 0 ? 1.1 : 0.9;
  // (delta)
  // camera.position.sub(controls.target).multiplyScalar(delta).add(controls.target);
}
const animateFocusTo = (targetPoint) => {
  // 当前相机和 target 的偏移向量
  const offset = new THREE.Vector3().subVectors(camera.position, controls.target);

  // 目标位置（保持偏移量不变，从同一角度看过去）
  const newCameraPos = new THREE.Vector3().addVectors(targetPoint, offset);

  // 使用 gsap 动画 camera.position 和 controls.target
  gsap.to(controls.target, {
    duration: 1.2,
    x: targetPoint.x,
    y: targetPoint.y,
    z: targetPoint.z,
    onUpdate: () => controls.update()
  });

  gsap.to(camera.position, {
    duration: 1.2,
    x: newCameraPos.x,
    y: newCameraPos.y,
    z: newCameraPos.z,
    onUpdate: () => controls.update()
  });
}
const handleClick = e => {
  // 1. 获取鼠标归一化设备坐标
  const rect = renderer.domElement.getBoundingClientRect();
  mouse.x = ((e.clientX - rect.left) / rect.width) * 2 - 1;
  mouse.y = -((e.clientY - rect.top) / rect.height) * 2 + 1;

  // 2. 使用 Raycaster 拾取
  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(scene.children, true);

  if (intersects.length > 0) {
    const targetPoint = intersects[0].point;
    animateFocusTo(targetPoint);
  }
}
onMounted(initCanvas)
</script>